package models.users

import play.api.Logging
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.jdbc.JdbcProfile

import java.sql.Timestamp
import java.time.LocalDateTime
import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class GyErpUsersRepository @Inject()(protected val dbConfigProvider: DatabaseConfigProvider,
                                     ugRepo: UserGroupRepository)(implicit executionContext: ExecutionContext)
  extends HasDatabaseConfigProvider[JdbcProfile] with Logging{

  import profile.api._

  private class GyErpUsersTable(tag: Tag) extends Table[GyErpUser](tag, "SYS_GYERP_USERS") {
    def id = column[Long]("ID", O.PrimaryKey) // = models.IntegerField(primary_key=True)

    def base_user_id = column[Option[Int]]("BASE_USER_ID") // = models.BigIntegerField(null=True,blank=True)

    def name = column[String]("NAME") // = models.CharField(max_length=20)

    def mobile = column[String]("MOBILE") // = models.CharField(max_length=20)

    def status = column[Int]("STATUS") // = models.SmallIntegerField(default=0)

    def disable_time = column[Option[Timestamp]]("DISABLE_TIME") // = models.DateTimeField(null=True,blank=True)

    def * = (
      id, base_user_id, name, mobile, status, disable_time
      ).<>((GyErpUser.apply _).tupled, GyErpUser.unapply)
  }

  private val gyErpUsersTable = TableQuery[GyErpUsersTable]

  private val accountTable = ugRepo.accountTable
  private val userInfoTable = ugRepo.userInfoTable

  ////////

  def userList() = db.run(gyErpUsersTable.map(f => f).result)

  def accountAll() = db.run(accountTable.filter(_.is_active === 1).sortBy(_.id).map(f => (f.id, f.username)).result)

  def userFindby(name: String, mobile: String, status: Int, page: Int = 1, limit: Int = 10) = {
    val q = gyErpUsersTable
      .filterIf(name.nonEmpty)(_.name like s"%$name%")
      .filterIf(mobile.nonEmpty)(_.mobile === mobile)
      .filterIf(status != -1)(_.status === status)
    val res = q.sortBy(_.id).drop((page - 1) * limit).take(limit)
    val qr = res joinLeft (accountTable) on (_.base_user_id === _.id)
    val total = q.length.result
    db.run(qr.map(f => (f._1, f._2.map(_.username))).result).zip(db.run(total))
  }

//  def findById(id: Long) = {
//    val find = for {
//      (gy, acc) <- gyErpUsersTable joinLeft accountTable on (_.base_user_id === _.id)
//    } yield (gy.id, gy.name, gy.mobile, gy.status, acc.map(_.is_active))
//    db.run(find.filter(_._1 === id).result)
//  }

  def findById(id: Long) = {
    db.run(gyErpUsersTable.filter(_.id === id).map(f => f.status).result)
  }

  def create(user: GyErpUser) = db.run {
    accountTable.filter(_.mobile === user.mobile).map(f => f.id).result
  }.flatMap { acc =>
    if (acc.isEmpty) db.run(gyErpUsersTable += user.copy(status = 9))
    else db.run(gyErpUsersTable += user.copy(base_user_id = acc.head))
  }

  def updateStatus(id: Long, status: Int) = db.run(
    if (status == 0) gyErpUsersTable.filter(_.id === id).map(f => (f.status, f.disable_time)).update((0, Some(Timestamp.valueOf(LocalDateTime.now()))))
    else gyErpUsersTable.filter(_.id === id).map(f => f.status).update(status)
  )

  def checkStatus(id: Long) = {
    val find = for {
      (gy, acc) <- gyErpUsersTable joinLeft accountTable on (_.base_user_id === _.id)
    } yield (gy.id, gy.name, gy.mobile, gy.status, acc.map(_.is_active))
    db.run(find.filter(_._1 === id).result).map {
      user => {
//        val seq = user.filter(u => u._4 == 2 && !u._5.getOrElse(true))
        val seq = user.filter(u => u._4 == 2 && u._5.getOrElse(1)==0)
        if (seq.nonEmpty) updateStatus(id, 3)
      }
    }

  }

  def updateBaseUsersId(id: Long, base_user_id: Option[Int], status: Int) = db.run(gyErpUsersTable.filter(_.id === id).map(f => (f.base_user_id, f.status)).update((base_user_id, status)))

  def updateDisableOnoff(id: Long) = db.run {
    gyErpUsersTable.filter(_.id === id).map(f => f.status).result
  }.flatMap { r =>
    val status = if (r.nonEmpty) r.head match {
      case 1 => 0
      case 2 => 1
      case 0 => 2
      case 3 => 1
      case _ => 9
    } else 2
    db.run(gyErpUsersTable.filter(_.id === id).map(f => f.status).update(status)).zip(Future(status))
  }

  def remove(id: Long) = db.run {
    gyErpUsersTable.filter(_.id === id).delete
  }
}
